/*----------------------------------------------------------------------------
Owner(s): Shane Whitfield
$Copyright: $
$Id: $
----------------------------------------------------------------------------*/

#include "level.h"
#include "timermgr.h"
#include "wave.h"
#include "go.h"
#include "player.h"
#include "engine.h"
#include "go_path.h"
#include "uimgr.h"

/* -------------------------------------------------------------------------*/
//globals
static bool (*s_fileLoader)(const char* i_filename, CLevel* io_level) = 0 ;

/* -------------------------------------------------------------------------*/

void CLevel::SetFileLoader(bool (*systemFileLoader)(const char* i_filename, CLevel* io_level))
{
    s_fileLoader = systemFileLoader;
}

CLevel::CLevel(const char* levelFileName)
{
	m_wave = NULL;
	m_state = EState_WaitingToStart;
	m_tState = 0.0;
	m_lastWave = NULL;
	m_curCommand = -1;
	
	load(levelFileName);
}

CLevel::~CLevel()
{
	//clear all the level commands
	for (int iCommand = 0; iCommand < m_levelCommands.size(); ++iCommand)
	{
		delete m_levelCommands[iCommand];
	}
	
	m_levelCommands.clear();
}

void CLevel::On_MineralCount(float i_mineralCount)
{
	g_player.SetMineralCount(i_mineralCount);
}

void CLevel::On_AddMinerals(float i_x, float i_y, float i_mineralCount)
{
	CGoMinerals* minerals = static_cast<CGoMinerals*>(g_gomgr.CreateGo(EClass_Minerals, Vector2f(i_x, i_y)));
	minerals->SetMineralCount(i_mineralCount);
}

void CLevel::On_AddWave(const char* i_fileName, float i_x, float i_y)
{
	CLevelCommandWave* command = new CLevelCommandWave(i_fileName, Vector2f(i_x, i_y));
	m_levelCommands.push_back(command);
	m_lastWave = command;
}

void CLevel::On_AddPause(float i_duration)
{
	m_levelCommands.push_back(new CLevelCommandPause(i_duration));
}

void CLevel::On_DisplayTimer(float i_secs)
{
	m_levelCommands.push_back(new CLevelCommandDisplayTimer(i_secs));
}

void CLevel::On_GoalSurviveWave()
{
	m_levelCommands.push_back(new CLevelCommandWait(m_lastWave));
}

void CLevel::On_GoalCollectMinerals(float i_mineralCount)
{
	m_levelCommands.push_back(new CLevelCommandGoalCollect(i_mineralCount));
}

void CLevel::On_Spawn(const char* i_className, float i_x, float i_y)
{
	Vector2f pos(i_x, i_y);
	g_gomgr.CreateGo(ClassFromString(i_className), pos)->Spawn(Vector2f::Zero);
}

void CLevel::On_AddSystemMessage(const char* i_title, const char* i_message, const char* i_accept)
{
	m_levelCommands.push_back(new CLevelCommandMessage(i_title, i_message, i_accept));
}

void CLevel::Update()
{
	for (;;)
	{
		EState prevState = m_state;
		switch (m_state)
		{
		case EState_ExecuteNextCommand:
			{
				setState(EState_Executing);
			}
			break;
		case EState_Executing:
			{
				if (m_levelCommands[m_curCommand]->IsComplete())
				{
					//if all the commands have been executed.. then we are complete
					if (m_levelCommands.size() <= m_curCommand + 1)
					{
						setState(EState_Complete);
					}
					else
					{
						setState(EState_ExecuteNextCommand);
					}
				}
			}
			break;
		}
		
		if (prevState == m_state)
		{
			break;
		}
	}
}

void CLevel::Start()
{
	if (m_state != EState_WaitingToStart)
	{
		printf("Cannont start till load is complete");
	}
	
	setState(EState_ExecuteNextCommand);
}

void CLevel::load(const char* i_levelFileName)
{		
	if(!s_fileLoader(i_levelFileName, this)) 
	{
		printf("Cannot open level file(%s)", i_levelFileName);
	}
}

void CLevel::setState(EState i_state)
{
	m_state = i_state;
	m_tState = T();
	
	switch (m_state)
	{
	case EState_ExecuteNextCommand :
		{
			m_curCommand++;
			m_levelCommands[m_curCommand]->Execute();
		}
		break;
	}
}

/*--------------------------------------------------------------------------*/ 					
bool CLevel::CLevelCommandWait::IsComplete() const
{
	if	(m_waveCommand)
	{
		return m_waveCommand->GetWave()->IsComplete();
	}
	
	return false;
}

/*--------------------------------------------------------------------------*/ 
void CLevel::CLevelCommandPause::Execute()
{
	m_tStart = T();
	printf("executing pause for %g secs\n", m_duration);
}

bool CLevel::CLevelCommandPause::IsComplete() const
{
	return (T() - m_tStart) > m_duration;
}

/*--------------------------------------------------------------------------*/

void CLevel::CLevelCommandWave::Execute()
{
	m_wave = new CWave(m_fileName, m_pos);
	if	(m_wave)
	{
		m_wave->Spawn();
	}
	
	printf("executing wave\n");
}

/*--------------------------------------------------------------------------*/
CLevel::CLevelCommandGoalCollect::CLevelCommandGoalCollect(float i_mineralCount)
{
	m_mineralCount = i_mineralCount;
}

bool CLevel::CLevelCommandGoalCollect::IsComplete() const
{
	return g_player.GetMineralCount() >= m_mineralCount;
}
							
/*--------------------------------------------------------------------------*/
void CLevel::CLevelCommandDisplayTimer::Execute()
{
	g_uimgr.SetGlobalTimer(m_duration);
	g_uimgr.StartGlobalTimer();
}

/*--------------------------------------------------------------------------*/
CLevel::CLevelCommandMessage::CLevelCommandMessage(const char* i_title, const char* i_message, const char* i_accept)
{
	m_title = new char[strlen(i_title) + 1];
	strcpy(m_title, i_title);
	m_message = new char[strlen(i_message) + 1];
	strcpy(m_message, i_message);
	m_accept = new char[strlen(i_accept) + 1];
	strcpy(m_accept, i_accept);
}

void CLevel::CLevelCommandMessage::Execute()
{
	g_engine.SystemMessage(m_title, m_message, m_accept, NULL);
}

bool CLevel::CLevelCommandMessage::IsComplete() const
{
	return !g_engine.IsSystemMessageShowing();
}

CLevel::CLevelCommandMessage::~CLevelCommandWait()
{
	delete m_title;
	delete m_message;
	delete m_accept;
}
/*-----------------------------------EOF!-----------------------------------*/ 
